package com.example.model;
import org.web3j.crypto.*;
import org.web3j.utils.Numeric;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

// 定义一个名为 User 的公共类，用于表示系统中的用户
public class User {
    // 定义一个私有字符串类型的变量，用于存储用户的唯一标识符，这里假设是用户的以太坊地址
    private String userAddress;
    // 定义一个私有枚举类型的变量，用于存储用户的角色，角色类型由 UserRole 枚举定义
    private UserRole userRole;
    // 定义一个私有布尔类型的变量，用于表示用户是否已注册
    private boolean isRegistered;

    private static final Map<String, User> userDatabase = new HashMap<>();

    /**
     * 定义一个枚举类型 UserRole，用于表示用户的不同角色
     */
    public enum UserRole {
        // 生产者角色
        PRODUCER,
        // 运输者角色
        TRANSPORTER,
        // 销售者角色
        SELLER,
        // 监管者角色
        REGULATOR,
        // 消费者角色
        CONSUMER
    }

    /**
     * 构造函数，用于初始化用户对象
     * @param userAddress 用户的唯一标识符（以太坊地址）
     * @param userRole 用户的角色
     * @param isRegistered 用户是否已注册的标志
     */
    public User(String userAddress, UserRole userRole, boolean isRegistered) {
        // 将传入的用户地址赋值给类的 userAddress 变量
        this.userAddress = userAddress;
        // 将传入的用户角色赋值给类的 userRole 变量
        this.userRole = userRole;
        // 将传入的用户注册状态赋值给类的 isRegistered 变量
        this.isRegistered = isRegistered;
    }

    /**
     * 获取用户的唯一标识符（以太坊地址）
     * @return 用户的以太坊地址
     */
    public String getUserAddress() {
        // 返回类的 userAddress 变量的值
        return userAddress;
    }

    /**
     * 设置用户的唯一标识符（以太坊地址）
     * @param userAddress 要设置的用户以太坊地址
     */
    public void setUserAddress(String userAddress) {
        // 将传入的用户地址赋值给类的 userAddress 变量
        this.userAddress = userAddress;
    }

    /**
     * 获取用户的角色
     * @return 用户的角色
     */
    public UserRole getUserRole() {
        // 返回类的 userRole 变量的值
        return userRole;
    }

    /**
     * 设置用户的角色
     * @param userRole 要设置的用户角色
     */
    public void setUserRole(UserRole userRole) {
        // 将传入的用户角色赋值给类的 userRole 变量
        this.userRole = userRole;
    }

    /**
     * 检查用户是否已注册
     * @return 如果用户已注册返回 true，否则返回 false
     */
    public boolean isRegistered() {
        // 返回类的 isRegistered 变量的值
        return isRegistered;
    }

    /**
     * 设置用户的注册状态
     * @param registered 要设置的用户注册状态
     */
    public void setRegistered(boolean registered) {
        // 将传入的注册状态赋值给类的 isRegistered 变量
        isRegistered = registered;
    }

    /**
     * 用户注册方法
     * @param userAddress 用户的以太坊地址
     * @param userRole 用户的角色
     * @return 注册成功返回 true，用户已存在则返回 false
     */
    public static boolean register(String userAddress, UserRole userRole) {
        if (userDatabase.containsKey(userAddress)) {
            return false;
        }
        User newUser = new User(userAddress, userRole, true);
        userDatabase.put(userAddress, newUser);
        return true;
    }

    /**
     * 用户登录方法
     * @param userAddress 用户的以太坊地址
     * @param message 用于签名的消息
     * @param signature 用户使用私钥对消息进行的签名
     * @return 登录成功返回 true，否则返回 false
     */
    public static boolean login(String userAddress, String message, String signature) {
        User user = userDatabase.get(userAddress);
        if (user == null ||!user.isRegistered()) {
            return false;
        }
        try {
            byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
            Sign.SignatureData signatureData = Sign.decodeSignature(signature);
            BigInteger publicKey = Sign.signedMessageToKey(messageBytes, signatureData);
            String recoveredAddress = Keys.getAddress(publicKey);
            return recoveredAddress.equals(Numeric.cleanHexPrefix(userAddress));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 重写 toString 方法，用于返回用户信息的字符串表示
     * @return 包含用户信息的字符串
     */
    @Override
    public String toString() {
        // 构建并返回一个包含用户所有信息的字符串
        return "User{" +
                "userAddress='" + userAddress + '\'' +
                ", userRole=" + userRole +
                ", isRegistered=" + isRegistered +
                '}';
    }
}